#include "log4cpp/Category.hh"
#include "log4cpp/Appender.hh"
#include "log4cpp/FileAppender.hh"
#include "log4cpp/OstreamAppender.hh"
#include "log4cpp/Layout.hh"
#include "log4cpp/BasicLayout.hh"
#include "log4cpp/Priority.hh"
using namespace log4cpp;

//Category 日志记录器
//Priority 优先级（过滤器）
//Layout 布局
//Appender 输出器（目的地）

int main(int argc, char** argv) {
    //基类指针指向派生类对象
	/* Appender *appender1 = new OstreamAppender("console", &std::cout); */
    //OstreamAppender构造函数的第一个参数表示目的地名字（随便写，只是给程序员一个提示）
    //第二个参数需要ostream * ,此处传入&cout，意味着输出器会是输出到终端
	OstreamAppender * appender1 = new OstreamAppender("console", &std::cout);
    //输出器指针调用setLayout函数，设定布局为BasicLayout
	appender1->setLayout(new BasicLayout());

    //FileAppender的构造函数的第一个参数表示目的地名字（随便写）
    //第二个参数表示保存日志的文件名
	FileAppender *appender2 = new FileAppender("default", "program.log");
	appender2->setLayout(new BasicLayout());


    //getRoot创建出根节点的Category对象，用引用root进行绑定
    //之后就直接在代码中用root指代根节点的Category对象
	Category& root = Category::getRoot();
    //根节点设置优先级为WARN级别，代表的是系统的优先级（门槛）
    //如果日志信息的优先级高于或等于系统的优先级，才会被处理
    //如果日志信息的优先级低于系统的优先级，会被直接过滤
	root.setPriority(Priority::WARN);
    //指定目的地（此处是输出到终端）
	root.addAppender(appender1);

    //getInstance创建叶节点的Category对象，会继承父节点的优先级和目的地
    //前面的sub1是引用的名字，在程序中使用
    //getInstance的参数sub1是Category的名字，代表日志来源
	Category& sub1 = Category::getInstance("sub1");
	/* Category& sub11 = Category::getInstance("sub1.sub11"); */

    //重新设置sub1的优先级（门槛）
    sub1.setPriority(Priority::INFO);
	sub1.addAppender(appender2);
    sub1.setAdditivity(false);//不再继承父节点的目的地

	// use of functions for logging messages
	root.error("root error");//ok
	root.info("root info");//pass
	sub1.error("sub1 error");//ok
	sub1.warn("sub1 warn");//ok
    sub1.info("sub1 info");

	// printf-style for logging variables
	root.warn("%d + %d == %s ?", 1, 1, "two");//ok

	// use of streams for logging messages
	root << Priority::ERROR << "Streamed root error";//ok
	root << Priority::INFO << "Streamed root info";//pass
	sub1 << Priority::ERROR << "Streamed sub1 error";//ok
	sub1 << Priority::WARN << "Streamed sub1 warn";//ok

	// or this way:
	root.errorStream() << "Another streamed error";//ok

	return 0;
}
